package designModel;
// 建造者（Builder）模式：将一个复杂对象分解成多个相对简单的部分，然后根据不同需要分别创建它们，最后构建成该复杂对象。 ☆☆☆☆☆
public class Builder {
    public static void main(String[] args) {
       /* HouseA houseA = new HouseA();
        houseA.build();*/


        HouseBuilder concreteBuilder = new ConcreteHouseBuilder();
        Director director1 = new Director(concreteBuilder);
        House concreteHouse = director1.constructHouse();
        System.out.println("混凝土房子 : " + concreteHouse);

        HouseBuilder luxuryBuilder = new LuxuryHouseBuilder();
        Director director2 = new Director(luxuryBuilder);
        House luxuryHouse = director2.constructHouse();
        System.out.println("豪华房屋 : " + luxuryHouse);
    }
}


/*abstract class House{
    private String foundation;
    private String structure;
    private String roof;
    private String interior;
    // abc 是过程  build 是创建 两者有耦合
    abstract void a();
    abstract void b();
    abstract void c();
    void build(){
        a();
        b();
        c();
        System.out.println("盖完了");
    }
}

class HouseA extends House {

    @Override
    void a() {
        System.out.println("盖房子步骤a");
    }

    @Override
    void b() {
        System.out.println("盖房子步骤b");
    }

    @Override
    void c() {
        System.out.println("盖房子步骤c");
    }
}*/

//
//        产品（Product）：表示正在构建的复杂对象。建造者模式的目标是构建这个产品。(产品的差异性不能过大)
//        抽象建造者（Abstract Builder）：定义了构建产品的步骤和方法，但没有具体的实现。不同的具体建造者可以实现不同的构建步骤，从而创建不同的产品变体。
//        具体建造者（Concrete Builder）：实现了抽象建造者定义的方法，完成了产品的构建过程。每个具体建造者负责构建特定的产品变体。
//        指导者（Director）：负责控制建造的过程。它通过将客户端与具体建造者分离，确保产品的构建是按照一定顺序和规则进行的。

// 好处在于能将产品与构造产品 分离
// 不同的具体建造者，可以创建不同的产品表示，而不改变客户端的代码。
// 便于扩展
class House {
    private String foundation;
    private String structure;
    private String roof;
    private String interior;

    public void setFoundation(String foundation) {
        this.foundation = foundation;
    }

    public void setStructure(String structure) {
        this.structure = structure;
    }

    public void setRoof(String roof) {
        this.roof = roof;
    }

    public void setInterior(String interior) {
        this.interior = interior;
    }

    @Override
    public String toString() {
        return "House [foundation=" + foundation + ", structure=" + structure + ", roof=" + roof + ", interior=" + interior + "]";
    }
}
// 然后，我们创建一个抽象建造者类 HouseBuilder，它定义了构建房屋的方法。
abstract class HouseBuilder {
    protected House house = new House();

    public abstract void buildFoundation();
    public abstract void buildStructure();
    public abstract void buildRoof();
    public abstract void buildInterior();

    public House getHouse() {
        return house;
    }
}
// 接下来，我们创建两个具体的建造者类 ConcreteHouseBuilder 和 LuxuryHouseBuilder
// 分别实现了不同类型房屋的构建过程。
// 具体建造者类 - 普通房屋
class ConcreteHouseBuilder extends HouseBuilder {
    @Override
    public void buildFoundation() {
        house.setFoundation("Standard Foundation");
    }

    @Override
    public void buildStructure() {
        house.setStructure("Standard Structure");
    }

    @Override
    public void buildRoof() {
        house.setRoof("Standard Roof");
    }

    @Override
    public void buildInterior() {
        house.setInterior("Standard Interior");
    }
}

// 3 具体建造者类 - 豪华房屋
class LuxuryHouseBuilder extends HouseBuilder {
    @Override
    public void buildFoundation() {
        house.setFoundation("Strong Foundation");
    }

    @Override
    public void buildStructure() {
        house.setStructure("Reinforced Structure");
    }

    @Override
    public void buildRoof() {
        house.setRoof("Elegant Roof");
    }

    @Override
    public void buildInterior() {
        house.setInterior("Luxury Interior");
    }
}
// 4 最后，我们创建指导者类 Director，它协调建造过程并返回构建的房屋对象。
class Director {
    private HouseBuilder builder;

    public Director(HouseBuilder builder) {
        this.builder = builder;
    }

    public House constructHouse() {
        builder.buildFoundation();
        builder.buildStructure();
        builder.buildRoof();
        builder.buildInterior();
        return builder.getHouse();
    }
}